package timesign

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"strconv"
	"time"
)

// Config 签名配置
type Config struct {
	Secret     string        // 签名密钥（必填）
	TimeWindow time.Duration // 时间窗口（默认5分钟）
	TimeFormat string        // 时间戳格式（默认Unix秒级）
}

// TimeSigner 签名处理器
type TimeSigner struct {
	config *Config
}

// New 初始化签名器
func New(secret string) (*TimeSigner, error) {
	config := Config{
		Secret:     secret,
		TimeWindow: 5 * time.Minute,
		TimeFormat: "unix",
	}
	return &TimeSigner{config: &config}, nil
}

// Verify 验证签名有效性
func (ts *TimeSigner) Verify(sign, timestamp string) bool {
	// 解析时间戳字符串为 time.Time 对象
	var t time.Time
	var err error

	if ts.config.TimeFormat == "unix" {
		// 处理Unix时间戳（字符串转int64）
		sec, err := strconv.ParseInt(timestamp, 10, 64) // 修正点：使用 strconv.ParseInt
		if err != nil {
			return false // 时间戳格式错误
		}
		t = time.Unix(sec, 0)
	} else {
		// 解析自定义格式时间戳
		t, err = time.Parse(ts.config.TimeFormat, timestamp)
		if err != nil {
			return false // 时间格式不匹配
		}
	}

	// 检查时间窗口（允许误差范围）
	if time.Since(t).Abs() > ts.config.TimeWindow {
		return false // 超出时间窗口
	}

	// 重新生成签名进行比对
	expectedSign, _ := ts.GenerateWithTime(t)
	return sign == expectedSign
}

// GenerateWithTime 根据指定时间生成签名
func (ts *TimeSigner) GenerateWithTime(t time.Time) (sign, timestamp string) {
	if ts.config.TimeFormat == "unix" {
		timestamp = fmt.Sprintf("%d", t.Unix())
	} else {
		timestamp = t.Format(ts.config.TimeFormat)
	}
	hash := md5.Sum([]byte(ts.config.Secret + timestamp))
	sign = hex.EncodeToString(hash[:])
	return
}
